package core

import (
	"context"
	"fmt"
	"github.com/APP/global"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type server interface {
	ListenAndServe() error
	Shutdown(context.Context) error
}

// initServer 启动 HTTP 服务，并实现优雅关闭机制
func initServer(address string, router *gin.Engine, readTimeout, writeTimeout time.Duration) {
	// 创建一个 HTTP 服务实例，配置监听地址、路由、读写超时、请求头大小限制
	srv := &http.Server{
		Addr:           address,      // 服务监听地址，例如 ":8080"
		Handler:        router,       // 使用 gin 引擎作为请求处理器
		ReadTimeout:    readTimeout,  // 设置读取请求的超时时间（包含头部和 body）
		WriteTimeout:   writeTimeout, // 设置写响应的超时时间
		MaxHeaderBytes: 1 << 20,      // 最大请求头为 1MB（1 << 20 = 1048576 字节）
	}

	// 启动服务放在一个 goroutine 中，防止阻塞主线程（用于后续监听系统信号）
	go func() {
		// ListenAndServe 会阻塞直到发生错误或服务关闭
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			// 如果发生的错误不是正常关闭引起的错误，则打印并记录错误，终止程序
			fmt.Printf("listen: %s\n", err)
			global.APP_LOG.Error("server启动失败", zap.Error(err))
			os.Exit(1)
		}
	}()

	// 创建一个用于接收系统中断信号的通道
	quit := make(chan os.Signal, 1)

	// 注册监听的信号类型（可被捕获的退出信号：SIGINT, SIGTERM）
	// - SIGINT 通常由 Ctrl+C 触发
	// - SIGTERM 是默认的 kill 命令发送的信号
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	// 阻塞，直到接收到退出信号
	<-quit
	global.APP_LOG.Info("关闭WEB服务...")

	// 创建一个上下文，设置最大等待时间为 5 秒，用于优雅关闭服务
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel() // 确保即使提前返回也会释放资源

	// 尝试优雅关闭 HTTP 服务（完成已有连接请求，拒绝新连接）
	if err := srv.Shutdown(ctx); err != nil {
		// 如果关闭过程中出错，记录致命错误并退出程序
		global.APP_LOG.Fatal("WEB服务关闭异常", zap.Error(err))
	}

	// 服务成功关闭
	global.APP_LOG.Info("WEB服务已关闭")
	err := zap.L().Sync()
	if err != nil {
		return
	}
}
